import struct
import time
from time import sleep

import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcp


class PlCConnect(object):
    def __init__(self, ip='192.168.10.98'):
        super(PlCConnect, self).__init__()
        # 仿真调试可以使用本机地址：127.0.0.1
        # 实际使用PLC地址，将client的地址设置在于server同一频段下，host填写server的地址
        self.ip = ip
        self.master = modbus_tcp.TcpMaster(host=self.ip)
        self.master.set_timeout(5.0)

    def writeIntNum(self, slave_id, flag, modbus_address, int_value):
        """
        写整数
        @param slave_id: slave号
        @param modbus_address: 写入plc中modbus地址 十六进制
        @param int_value: 写入的整数值(浮点数*10倍，写入整数)
        @param flag: 区分线圈M(COLW)和寄存器D(REGW)
        @return:
        """
        if flag == "REGW":
            self.master.execute(slave_id, cst.WRITE_SINGLE_REGISTER, modbus_address, output_value=int_value)
        elif flag == "COLW":
            self.master.execute(slave_id, cst.WRITE_SINGLE_COIL, modbus_address, output_value=int_value)

    def readIntNum(self, slave_id, flag, modbus_address):
        """
        读整数
        @param slave_id: slave号
        @param modbus_address:
        @param flag: 读线圈M指令 COLR
                     读输入线圈指令 INPR（不支持读信捷PLC 的输入线圈）
                     读出寄存器D内容 REGR
                     读输入寄存器指令 INRR
        @return: 返回读到的值，默认-99(浮点数=整数/1000)
        """
        result_int = -99
        if flag == "COLR":
            result_int = self.master.execute(slave_id, cst.READ_COILS, modbus_address, 1)
        elif flag == "INRR":
            result_int = self.master.execute(slave_id, cst.READ_INPUT_REGISTERS, modbus_address, 1)
        elif flag == "REGR":
            result_int = self.master.execute(slave_id, cst.READ_HOLDING_REGISTERS, modbus_address, 1)
        return result_int

    def move1200(self, pos, speed):
        # D1050 目标位置
        self.writeIntNum(1, "REGW", 1050, pos)
        # D1100 目标速度
        self.writeIntNum(1, "REGW", 1100, speed)
        # D1150 减速度
        self.writeIntNum(1, "REGW", 1150, 80)
        # sleep(0.5)
        # M55 齿轮绑定
        # self.writeIntNum(1, "COLW", 55, 1)
        sleep(0.5)
        # M40 启动
        self.writeIntNum(1, "COLW", 40, 1)

    def move700(self, pos, speed):
        # D500 目标位置
        self.writeIntNum(1, "REGW", 500, pos)
        # D504 目标速度
        self.writeIntNum(1, "REGW", 504, speed)
        # D508 加减速时间
        self.writeIntNum(1, "REGW", 508, 100)
        # M100 启动
        self.writeIntNum(1, "COLW", 100, 1)

    def enabling(self):
        # M1 使能 M55 齿轮绑定
        self.writeIntNum(1, "COLW", 1, 1)
        # M101 脉冲使能
        self.writeIntNum(1, "COLW", 101, 1)
        sleep(0.5)
        self.writeIntNum(1, "COLW", 55, 1)

    def disabling(self):
        # M1 M101 断开使能
        self.writeIntNum(1, "COLW", 1, 0)
        self.writeIntNum(1, "COLW", 101, 0)

    def test_M0(self):

        # # D10 置5
        self.writeIntNum(1, "REGW", 10, 5)
        # # D20 置5
        self.writeIntNum(1, "REGW", 20, 5)


        # Y协议地址0开始
        # M协议地址2000开始
        # Y0置1
        self.writeIntNum(1, "COLW", 0, 1)
        # time.sleep(0.5)
        # D30 = D10 + D20
        res = self.readIntNum(1, "REGR", 30)[0]
        print(res)

        # Y0置0
        self.writeIntNum(1, "COLW", 0, 0)

if __name__ == '__main__':
    plc_connection = PlCConnect()

    plc_connection.test_M0()
    # plc_connection.enabling()
    # plc_connection.move700(pos=493, speed=70)
    # plc_connection.move1200(pos=-5959, speed=80)
    # plc_connection.writeIntNum(1, "COLW", 100, 0)

    # print(plc_connection.readIntNum(1, "COLR", 40)[0])
    # plc_connection.disabling()
